import { Injectable, BadRequestException, NotFoundException, ConflictException } from '@nestjs/common'
import { DatabaseService } from '../../database/database.service'
import { LoggerService } from '../../common/logger/logger.service'
import { CreateCategoryDto, UpdateCategoryDto, BatchCategoryDto } from './dto'

@Injectable()
export class CategoryService {
  constructor(
    private readonly databaseService: DatabaseService,
    private readonly logger: LoggerService
  ) {}

  // 创建分类
  async create(createCategoryDto: any, operatorId: string): Promise<any> {
    try {
      // 生成唯一的slug
      let slug = this.generateSlug(createCategoryDto.name)
      const existingSlug = await this.databaseService.category.findFirst({
        where: { slug }
      })

      if (existingSlug) {
        slug = `${slug}-${Date.now()}`
      }

      const category = await this.databaseService.category.create({
        data: {
          ...createCategoryDto,
          slug,
          createdBy: operatorId,
          updatedBy: operatorId
        },
        include: {
          parent: true,
          children: true,
          _count: { select: { posts: true } }
        }
      })

      this.logger.log(`Category created: ${category.id}`, 'CategoryService')
      return category
    } catch (error) {
      this.logger.error(`Failed to create category: ${error.message}`, error.stack, 'CategoryService')
      throw new BadRequestException('创建分类失败')
    }
  }

  // 生成slug
  private generateSlug(name: string): string {
    return name
      .toLowerCase()
      .replace(/[^a-z0-9\u4e00-\u9fff]+/g, '-')
      .replace(/^-+|-+$/g, '')
  }

  // 获取所有分类（树形结构）
  async getCategories() {
    try {
      const categories = await this.databaseService.category.findMany({
        include: {
          parent: true,
          children: {
            include: {
              children: true,
              _count: { select: { posts: true } }
            }
          },
          _count: { select: { posts: true } }
        },
        orderBy: { createdAt: 'asc' }
      })

      // 构建树形结构
      const categoryTree = this.buildCategoryTree(categories)
      return categoryTree
    } catch (error) {
      this.logger.error(`Failed to get categories: ${error.message}`, error.stack, 'CategoryService')
      throw new BadRequestException('获取分类列表失败')
    }
  }

  async search(query: string, limit: number = 10): Promise<any[]> {
    const categories = await this.databaseService.category.findMany({
      where: {
        OR: [
          { name: { contains: query, mode: 'insensitive' } },
          { description: { contains: query, mode: 'insensitive' } },
          { slug: { contains: query, mode: 'insensitive' } }
        ],
        isActive: true
      },
      take: limit,
      orderBy: { name: 'asc' }
    })

    return categories
  }

  async findById(
    id: string,
    options: {
      includeChildren?: boolean
      includeParent?: boolean
      includeContent?: boolean
    } = {}
  ): Promise<any> {
    const category = await this.databaseService.category.findUnique({
      where: { id },
      include: {
        parent: options.includeParent,
        children: options.includeChildren,
        posts: options.includeContent
      }
    })

    if (!category) {
      throw new NotFoundException(`分类不存在: ${id}`)
    }

    return category
  }

  async findAll(
    options: {
      includeChildren?: boolean
      includeParent?: boolean
      includeContent?: boolean
      parentId?: string
      level?: number
      isActive?: boolean
    } = {}
  ): Promise<any[]> {
    const where: any = {}

    if (options.parentId !== undefined) {
      where.parentId = options.parentId
    }

    if (options.level !== undefined) {
      where.level = options.level
    }

    if (options.isActive !== undefined) {
      where.isActive = options.isActive
    }

    const categories = await this.databaseService.category.findMany({
      where,
      include: {
        parent: options.includeParent,
        children: options.includeChildren,
        posts: options.includeContent
      },
      orderBy: { sortOrder: 'asc' }
    })

    return categories
  }

  // 获取分类详情
  async getCategoryById(id: string) {
    try {
      const category = await this.databaseService.category.findUnique({
        where: { id },
        include: {
          parent: true,
          children: {
            include: {
              _count: { select: { posts: true } }
            }
          },
          posts: {
            where: { status: 'PUBLISHED' },
            include: {
              author: { select: { id: true, username: true } },
              _count: { select: { comments: true } }
            },
            orderBy: { publishedAt: 'desc' },
            take: 10
          },
          _count: { select: { posts: true } }
        }
      })

      if (!category) {
        throw new NotFoundException('分类不存在')
      }

      return category
    } catch (error) {
      if (error instanceof NotFoundException) {
        throw error
      }
      this.logger.error(`Failed to get category: ${error.message}`, error.stack, 'CategoryService')
      throw new BadRequestException('获取分类详情失败')
    }
  }

  // 更新分类
  async updateCategory(id: string, data: UpdateCategoryDto): Promise<any> {
    try {
      const existingCategory = await this.databaseService.category.findUnique({
        where: { id }
      })

      if (!existingCategory) {
        throw new NotFoundException('分类不存在')
      }

      // 检查分类名是否已被其他分类使用
      if (data.name && data.name !== existingCategory.name) {
        const duplicateCategory = await this.databaseService.category.findFirst({
          where: {
            name: data.name,
            id: { not: id }
          }
        })

        if (duplicateCategory) {
          throw new ConflictException('分类名称已存在')
        }
      }

      // 如果要设置父分类，检查父分类是否存在且不是自己或自己的子分类
      if (data.parentId) {
        if (data.parentId === id) {
          throw new BadRequestException('不能将自己设为父分类')
        }

        const parentCategory = await this.databaseService.category.findUnique({
          where: { id: data.parentId }
        })

        if (!parentCategory) {
          throw new NotFoundException('父分类不存在')
        }

        // 检查是否会形成循环引用
        const isDescendant = await this.isDescendantOf(data.parentId, id)
        if (isDescendant) {
          throw new BadRequestException('不能将子分类设为父分类')
        }
      }

      const updatedCategory = await this.databaseService.category.update({
        where: { id },
        data: {
          ...data,
          updatedAt: new Date()
        },
        include: {
          parent: true,
          children: true,
          _count: { select: { posts: true } }
        }
      })

      this.logger.log(`Category updated: ${id}`, 'CategoryService')
      return updatedCategory
    } catch (error) {
      if (
        error instanceof NotFoundException ||
        error instanceof ConflictException ||
        error instanceof BadRequestException
      ) {
        throw error
      }
      this.logger.error(`Failed to update category: ${error.message}`, error.stack, 'CategoryService')
      throw new BadRequestException('更新分类失败')
    }
  }

  // 删除分类
  async deleteCategory(id: string) {
    try {
      const category = await this.databaseService.category.findUnique({
        where: { id },
        include: {
          children: true,
          posts: true
        }
      })

      if (!category) {
        throw new NotFoundException('分类不存在')
      }

      // 检查是否有子分类
      if (category.children.length > 0) {
        throw new BadRequestException('请先删除子分类')
      }

      // 检查是否有关联的文章
      if (category.posts.length > 0) {
        throw new BadRequestException('该分类下还有文章，无法删除')
      }

      await this.databaseService.category.delete({
        where: { id }
      })

      this.logger.log(`Category deleted: ${id}`, 'CategoryService')
      return { message: '分类删除成功' }
    } catch (error) {
      if (error instanceof NotFoundException || error instanceof BadRequestException) {
        throw error
      }
      this.logger.error(`Failed to delete category: ${error.message}`, error.stack, 'CategoryService')
      throw new BadRequestException('删除分类失败')
    }
  }

  // 获取分类树
  async getTree(maxDepth?: number, includeEmpty = true): Promise<any[]> {
    try {
      const categories = await this.databaseService.category.findMany({
        include: {
          _count: { select: { posts: true } }
        },
        orderBy: { sortOrder: 'asc' }
      })

      // 过滤空分类
      const filteredCategories = includeEmpty ? categories : categories.filter(cat => cat._count.posts > 0)

      const tree = this.buildCategoryTree(filteredCategories)

      // 限制深度
      if (maxDepth !== undefined) {
        return this.limitTreeDepth(tree, maxDepth)
      }

      return tree
    } catch (error) {
      this.logger.error(`Failed to get category tree: ${error.message}`, error.stack, 'CategoryService')
      throw new BadRequestException('获取分类树失败')
    }
  }

  // 限制树的深度
  private limitTreeDepth(tree: any[], maxDepth: number, currentDepth = 0): any[] {
    if (currentDepth >= maxDepth) {
      return tree.map(node => ({ ...node, children: [] }))
    }

    return tree.map(node => ({
      ...node,
      children: this.limitTreeDepth(node.children || [], maxDepth, currentDepth + 1)
    }))
  }

  // 构建分类树形结构
  private buildCategoryTree(categories: any[]): any[] {
    const categoryMap = new Map()
    const rootCategories: any[] = []

    // 创建分类映射
    categories.forEach(category => {
      categoryMap.set(category.id, { ...category, children: [] })
    })

    // 构建树形结构
    categories.forEach(category => {
      const categoryNode = categoryMap.get(category.id)
      if (category.parentId) {
        const parent = categoryMap.get(category.parentId)
        if (parent) {
          parent.children.push(categoryNode)
        }
      } else {
        rootCategories.push(categoryNode)
      }
    })

    return rootCategories
  }

  // 检查是否为子分类
  private async isDescendantOf(ancestorId: string, descendantId: string): Promise<boolean> {
    const descendants = await this.databaseService.category.findMany({
      where: { parentId: descendantId }
    })

    for (const descendant of descendants) {
      if (descendant.id === ancestorId) {
        return true
      }
      if (await this.isDescendantOf(ancestorId, descendant.id)) {
        return true
      }
    }

    return false
  }

  // 移动分类
  async moveCategory(id: string, newParentId?: string) {
    try {
      const category = await this.databaseService.category.findUnique({
        where: { id }
      })

      if (!category) {
        throw new NotFoundException('分类不存在')
      }

      if (newParentId) {
        if (newParentId === id) {
          throw new BadRequestException('不能将自己设为父分类')
        }

        const parentCategory = await this.databaseService.category.findUnique({
          where: { id: newParentId }
        })

        if (!parentCategory) {
          throw new NotFoundException('目标父分类不存在')
        }

        // 检查是否会形成循环引用
        const isDescendant = await this.isDescendantOf(newParentId, id)
        if (isDescendant) {
          throw new BadRequestException('不能将分类移动到其子分类下')
        }
      }

      const updatedCategory = await this.databaseService.category.update({
        where: { id },
        data: {
          parentId: newParentId,
          updatedAt: new Date()
        },
        include: {
          parent: true,
          children: true,
          _count: { select: { posts: true } }
        }
      })

      this.logger.log(`Category moved: ${id}`, 'CategoryService')
      return updatedCategory
    } catch (error) {
      if (error instanceof NotFoundException || error instanceof BadRequestException) {
        throw error
      }
      this.logger.error(`Failed to move category: ${error.message}`, error.stack, 'CategoryService')
      throw new BadRequestException('移动分类失败')
    }
  }

  // 验证分类树
  async validateTree(): Promise<{
    isValid: boolean
    issues: Array<{
      type: string
      categoryId: string
      message: string
    }>
  }> {
    try {
      const categories = await this.databaseService.category.findMany()
      const issues: Array<{
        type: string
        categoryId: string
        message: string
      }> = []

      // 检查循环引用
      for (const category of categories) {
        if (category.parentId) {
          const isCircular = await this.isDescendantOf(category.id, category.parentId)
          if (isCircular) {
            issues.push({
              type: 'circular_reference',
              categoryId: category.id,
              message: '存在循环引用'
            })
          }
        }
      }

      // 检查孤儿节点
      for (const category of categories) {
        if (category.parentId) {
          const parent = categories.find(c => c.id === category.parentId)
          if (!parent) {
            issues.push({
              type: 'orphan_node',
              categoryId: category.id,
              message: '父分类不存在'
            })
          }
        }
      }

      return {
        isValid: issues.length === 0,
        issues
      }
    } catch (error) {
      this.logger.error(`Failed to validate tree: ${error.message}`, error.stack, 'CategoryService')
      throw new BadRequestException('验证分类树失败')
    }
  }

  // 根据别名查找分类
  async findBySlug(
    slug: string,
    options: {
      includeChildren?: boolean
      includeContent?: boolean
    } = {}
  ): Promise<any> {
    try {
      const category = await this.databaseService.category.findFirst({
        where: { slug },
        include: {
          parent: true,
          children: options.includeChildren
            ? {
                include: {
                  _count: { select: { posts: true } }
                }
              }
            : false,
          posts: options.includeContent
            ? {
                where: { status: 'PUBLISHED' },
                include: {
                  author: { select: { id: true, username: true } },
                  _count: { select: { comments: true } }
                },
                orderBy: { publishedAt: 'desc' },
                take: 10
              }
            : false,
          _count: { select: { posts: true } }
        }
      })

      if (!category) {
        throw new NotFoundException('分类不存在')
      }

      return category
    } catch (error) {
      if (error instanceof NotFoundException) {
        throw error
      }
      this.logger.error(`Failed to find category by slug: ${error.message}`, error.stack, 'CategoryService')
      throw new BadRequestException('查找分类失败')
    }
  }

  // 获取分类内容
  async getCategoryContent(
    id: string,
    options: {
      page?: number
      limit?: number
      includeChildren?: boolean
      status?: string
      type?: string
    } = {}
  ): Promise<any> {
    try {
      const { page = 1, limit = 20, includeChildren = false, status, type } = options
      const skip = (page - 1) * limit

      const whereClause: any = {
        categoryId: includeChildren ? { in: await this.getCategoryIds(id) } : id
      }

      if (status) {
        whereClause.status = status
      }

      if (type) {
        whereClause.type = type
      }

      const [posts, total] = await Promise.all([
        this.databaseService.post.findMany({
          where: whereClause,
          include: {
            author: { select: { id: true, username: true } },
            category: { select: { id: true, name: true, slug: true } },
            _count: { select: { comments: true } }
          },
          orderBy: { publishedAt: 'desc' },
          skip,
          take: limit
        }),
        this.databaseService.post.count({ where: whereClause })
      ])

      return {
        data: posts,
        total,
        page,
        limit,
        totalPages: Math.ceil(total / limit),
        hasNext: page * limit < total,
        hasPrev: page > 1
      }
    } catch (error) {
      this.logger.error(`Failed to get category content: ${error.message}`, error.stack, 'CategoryService')
      throw new BadRequestException('获取分类内容失败')
    }
  }

  // 获取分类ID列表（包括子分类）
  private async getCategoryIds(categoryId: string): Promise<string[]> {
    const ids = [categoryId]
    const children = await this.databaseService.category.findMany({
      where: { parentId: categoryId },
      select: { id: true }
    })

    for (const child of children) {
      const childIds = await this.getCategoryIds(child.id)
      ids.push(...childIds)
    }

    return ids
  }

  // 批量操作
  async batchOperation(
    batchDto: BatchCategoryDto,
    operatorId: string
  ): Promise<{
    success: number
    failed: number
    errors: Array<{ index: number; error: string }>
  }> {
    const results = {
      success: 0,
      failed: 0,
      errors: [] as Array<{ index: number; error: string }>
    }

    for (let i = 0; i < batchDto.items.length; i++) {
      try {
        const item = batchDto.items[i]

        switch (batchDto.operation) {
          case 'create':
            await this.create(item as CreateCategoryDto, 'system')
            break
          case 'update':
            if ('id' in item) {
              const { id, ...updateData } = item as any
              await this.updateCategory(id, updateData)
            } else {
              throw new Error('更新操作缺少ID')
            }
            break
          case 'delete':
            if ('id' in item) {
              await this.deleteCategory((item as any).id)
            } else {
              throw new Error('删除操作缺少ID')
            }
            break
          default:
            throw new Error('不支持的操作类型')
        }

        results.success++
      } catch (error) {
        results.failed++
        results.errors.push({
          index: i,
          error: error.message
        })
      }
    }

    return results
  }

  // 重建分类树
  async rebuildTree(operatorId: string): Promise<{ message: string; processedCount: number }> {
    try {
      const categories = await this.databaseService.category.findMany()
      let processedCount = 0

      // 重新计算每个分类的层级和路径
      for (const category of categories) {
        const path = await this.buildCategoryPath(category.id)
        const level = path.split('/').length - 1

        await this.databaseService.category.update({
          where: { id: category.id },
          data: {
            level,
            path
          }
        })

        processedCount++
      }

      this.logger.log(
        `Category tree rebuilt by ${operatorId}, processed ${processedCount} categories`,
        'CategoryService'
      )

      return {
        message: '分类树重建成功',
        processedCount
      }
    } catch (error) {
      this.logger.error(`Failed to rebuild tree: ${error.message}`, error.stack, 'CategoryService')
      throw new BadRequestException('重建分类树失败')
    }
  }

  // 构建分类路径
  private async buildCategoryPath(categoryId: string): Promise<string> {
    const category = await this.databaseService.category.findUnique({
      where: { id: categoryId },
      include: { parent: true }
    })

    if (!category) {
      throw new NotFoundException('分类不存在')
    }

    const pathSegments = [category.slug]
    let currentCategory = category

    while (currentCategory.parent) {
      pathSegments.unshift(currentCategory.parent.slug)
      currentCategory = await this.databaseService.category.findUnique({
        where: { id: currentCategory.parent.id },
        include: { parent: true }
      })
    }

    return `/${pathSegments.join('/')}`
  }

  async getChildren(id: string, recursive = false, includeContent = false): Promise<any[]> {
    const include: any = {
      children: recursive
    }

    if (includeContent) {
      include.posts = true
    }

    const category = await this.databaseService.category.findUnique({
      where: { id },
      include
    })

    if (!category) {
      throw new NotFoundException('分类不存在')
    }

    return category.children || []
  }

  async getAncestors(id: string): Promise<any[]> {
    const category = await this.databaseService.category.findUnique({
      where: { id },
      include: { parent: true }
    })

    if (!category) {
      throw new NotFoundException('分类不存在')
    }

    const ancestors = []
    let currentCategory = category.parent

    while (currentCategory) {
      ancestors.unshift(currentCategory)
      const parentCategory = await this.databaseService.category.findUnique({
        where: { id: currentCategory.id },
        include: { parent: true }
      })
      currentCategory = parentCategory?.parent
    }

    return ancestors
  }

  async getSiblings(id: string, includeSelf = false): Promise<any[]> {
    const category = await this.databaseService.category.findUnique({
      where: { id }
    })

    if (!category) {
      throw new NotFoundException('分类不存在')
    }

    const where: any = {
      parentId: category.parentId
    }

    if (!includeSelf) {
      where.id = { not: id }
    }

    return this.databaseService.category.findMany({
      where,
      orderBy: { sortOrder: 'asc' }
    })
  }

  async remove(id: string, moveContentTo?: string, operatorId?: string): Promise<void> {
    const category = await this.databaseService.category.findUnique({
      where: { id },
      include: { children: true, posts: true }
    })

    if (!category) {
      throw new NotFoundException('分类不存在')
    }

    // 如果有子分类，需要先处理子分类
    if (category.children && category.children.length > 0) {
      if (moveContentTo) {
        // 将子分类移动到指定分类下
        await this.databaseService.category.updateMany({
          where: { parentId: id },
          data: { parentId: moveContentTo }
        })
      } else {
        // 将子分类移动到根级别
        await this.databaseService.category.updateMany({
          where: { parentId: id },
          data: { parentId: null }
        })
      }
    }

    // 处理关联的内容
    if (category.posts && category.posts.length > 0) {
      if (moveContentTo) {
        // 将内容移动到指定分类
        await this.databaseService.post.updateMany({
          where: { categoryId: id },
          data: { categoryId: moveContentTo }
        })
      } else {
        // 移除分类关联
        await this.databaseService.post.updateMany({
          where: { categoryId: id },
          data: { categoryId: null }
        })
      }
    }

    // 删除分类
    await this.databaseService.category.delete({
      where: { id }
    })
  }

  async move(id: string, operatorId: string, newParentId?: string, position?: number): Promise<any> {
    const category = await this.databaseService.category.findUnique({
      where: { id }
    })

    if (!category) {
      throw new NotFoundException('分类不存在')
    }

    // 检查新父分类是否存在
    if (newParentId) {
      const newParent = await this.databaseService.category.findUnique({
        where: { id: newParentId }
      })
      if (!newParent) {
        throw new NotFoundException('目标父分类不存在')
      }
    }

    // 更新分类的父级关系
    const updatedCategory = await this.databaseService.category.update({
      where: { id },
      data: { parentId: newParentId }
    })

    // 重建分类树
    await this.rebuildTree(operatorId)

    return updatedCategory
  }

  async updateSortOrder(id: string, sortOrder: number, operatorId?: string): Promise<any> {
    const category = await this.databaseService.category.findUnique({
      where: { id }
    })

    if (!category) {
      throw new NotFoundException('分类不存在')
    }

    return this.databaseService.category.update({
      where: { id },
      data: { sortOrder }
    })
  }

  async getRootCategories(includeChildren = false): Promise<any[]> {
    const include: any = {}
    if (includeChildren) {
      include.children = true
    }

    return this.databaseService.category.findMany({
      where: { parentId: null },
      include,
      orderBy: { sortOrder: 'asc' }
    })
  }

  async getPopularCategories(limit = 10): Promise<any[]> {
    return this.databaseService.category.findMany({
      include: {
        _count: {
          select: { posts: true }
        }
      },
      orderBy: {
        posts: {
          _count: 'desc'
        }
      },
      take: limit
    })
  }

  async getStats(): Promise<any> {
    const [total, active, withContent] = await Promise.all([
      this.databaseService.category.count(),
      this.databaseService.category.count({ where: { isActive: true } }),
      this.databaseService.category.count({
        where: {
          posts: {
            some: {}
          }
        }
      })
    ])

    return {
      total,
      active,
      withContent,
      empty: total - withContent
    }
  }

  async update(id: string, updateCategoryDto: UpdateCategoryDto): Promise<any> {
    const category = await this.databaseService.category.findUnique({
      where: { id }
    })

    if (!category) {
      throw new NotFoundException('分类不存在')
    }

    // 如果更新了slug，需要检查唯一性
    if (updateCategoryDto.slug && updateCategoryDto.slug !== category.slug) {
      const existingCategory = await this.databaseService.category.findFirst({
        where: {
          slug: updateCategoryDto.slug,
          id: { not: id }
        }
      })

      if (existingCategory) {
        throw new BadRequestException('分类别名已存在')
      }
    }

    return this.databaseService.category.update({
      where: { id },
      data: updateCategoryDto
    })
  }
}
